Skip to main content

Custom Integration - JavaScript

Dependencies

PopulateTable

PopulateTable
// Asynchronous function to populate a table with data
async function PopulateTable(data, sectionName)
{
const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
var sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
const sectionRootFolder = $(`span[id='${sectionName} details']`).data('rootfolder');
const enableDeletion = $(`span[id='${sectionName} details']`).data('enabledeletion');
const enableCollaboration = $(`span[id='${sectionName} details']`).data('enablecollaboration');

// Convert the string to a boolean
const isDeletionEnabled = enableDeletion.toLowerCase() === 'true';
const isCollaborationEnabled = enableCollaboration.toLowerCase() === 'true';

$(`div[id="${sectionName}"]`).find(`ul#pagination-list[data-attribute="${sectionName}"]`).remove()
// Extract unique editorIds from the provided data
//const editorIds = [...new Set(data.map(item => item.EditorId))];

// Fetch editor results for the editorIds from SharePoint using an asynchronous function
//const editorResults = await GetSharePointFileEditors({ "SharePoint Site": sectionSharePointSite, "EditorId": editorIds });

// Initialize an empty string to store table rows
let tableRows = '';

// Initialize default page Number
let pageNumber = 1;

// Iterate through each item in the provided data, pass in the items index
data.forEach((item, index) => {
// Find the corresponding editor for the current item
//const editor = editorResults.find(editor => editor.EditorID === item.EditorId);

// If an editor is found, update the item's EditorName
// if (editor)
// {
// item.EditorName = editor.EditorName;
// }

// Allocate 10 items per page
pageNumber = Math.floor(index / 15) + 1;

item.EditorName = "SharePoint App";

// Determine the item type (Folder or File) based on FileSystemObjectType
const itemType = item.FileSystemObjectType === 1 ? "Folder" : "File";

const itemModified = new Date(item.Modified);

// Extract day, month, and year components from the Date object
const day = itemModified.getDate();
const month = itemModified.getMonth() + 1; // Months are zero-based, so we add 1
const year = itemModified.getFullYear();

// Create a formatted string representing the modification date
const modifiedOn = `${day}-${month}-${year}`;

// Determine the icon based on the item type
const icon = itemType === "Folder" ? '<i class="fa fa-folder-open-o fa-lg" aria-hidden="true"></i> ' : '<i class="fa fa-file-o fa-lg" aria-hidden="true"></i> ';

const fontSize = "16px"; // Set your desired font size here

// Create a table row HTML string for the current item
const tableRow = `<tr data-id="${itemType}" data-entity="fullName" page-number="${pageNumber}" data-name="${item.FileLeafRef}" style="text-align: center;">
<td data-type="System.String" data-attribute="tt_name" aria-readonly="true" data-th="Name" aria-label="${item.FileLeafRef}">
<div style="display: flex; align-items: center; justify-content: center;">
<div style="flex: 1; text-align: left;">
<a id="${itemType}" title="${itemType === 'File' ? `Download File` : `Open Folder`}" onclick="${itemType === 'File' ? `downloadFile('${item.FileLeafRef}','${item.Id}','${sectionName}')` : `OpenFolder('/${item.FileLeafRef}', 0, '${sectionName}')`}" style="font-size: ${fontSize};padding-right: 10px;">
${icon}
</a>
</div>
<div style="flex: 11; font-size: ${fontSize}; text-align: left;">
<a id="${itemType}" title="${itemType === 'File' ? `Download File` : `Open Folder`}" onclick="${itemType === 'File' ? `downloadFile('${item.FileLeafRef}','${item.Id}','${sectionName}')` : `OpenFolder('/${item.FileLeafRef}', 0, '${sectionName}')`}">
${item.FileLeafRef}
</a>
</div>
</div>
</td>
<!-- <td data-type="System.String" data-attribute="tt_id" data-value="${item.Id}" aria-readonly="true" data-th="ID" aria-label="${item.Id}" style="font-size: ${fontSize};">${item.Id}</td> -->
<td data-type="System.String" data-attribute="tt_modifiedOn" data-value="${modifiedOn}" aria-readonly="true" data-th="Modified On" aria-label="${modifiedOn}" style="font-size: ${fontSize};">${modifiedOn}</td>
<!-- <td data-type="System.String" data-attribute="tt_modifiedBy" data-value="${item.EditorName}" aria-readonly="true" data-th="Modified By" aria-label="${item.EditorName}" style="font-size: ${fontSize};">${item.EditorName}</td> -->
<td data-type="System.String" data-attribute="tt_Actions" data-value="${item.Collaboration_x0020_Url}" aria-readonly="true" data-th="Actions" aria-label="${item.Collaboration_x0020_Url}" style="font-size: ${fontSize}; text-align: center;">
${isCollaborationEnabled ? `<a title="Collaborate on File" id="collaborationLink${itemType}" href="${item.Collaboration_x0020_Url}" target="_blank"><i class="fa fa-pencil-square-o fa-lg" aria-hidden="true"></i></a>` : ''}
<a id="downloadLink${itemType}" title="Download File" onclick="downloadFile('${item.FileLeafRef}','${item.Id}','${sectionName}')"><i class="fa fa-download fa-lg" aria-hidden="true"></i></a>
${isDeletionEnabled ? `<a title="Delete File" id="deletionLink${itemType}" onclick="openDeleteModal('${item.FileLeafRef.replace(/'/g, "\\'")}', '${item.Id}', '${sectionName}')"><i class="fa fa-trash fa-lg" aria-hidden="true"></i></a>` : ''}
</td>
</tr>`;

// Concatenate the current table row to the overall tableRows string
tableRows += tableRow;
});

//Create the navigation buttons for the pages
const sectionPages = `<nav aria-label="Page navigation" style="text-align: center;">
<ul class="pagination" id="pagination-list" data-attribute="${sectionName}">
</ul>
</nav>`

// Set the innerHTML of the table body for the section to the constructed tableRows
$(`div[id="${sectionName}"]`).find(`tbody[id="${sectionName}"]`)[0].innerHTML = tableRows;

// Set the innerHTML of the table body for the section to the constructed tableRows
$(`div[id="${sectionName}"]`).find(`tbody[id="${sectionName}"]`)[0].innerHTML = tableRows;

// If there is more than one page, show the navigation
if(pageNumber > 1)
{
$(`div[id="${sectionName}"]`).append(sectionPages);
}

const paginationList = $(`div[id="${sectionName}"]`).find(`ul#pagination-list[data-attribute="${sectionName}"]`);

// Append the Page buttons to the navigation
for (var i = 1; i <= pageNumber; i++) {
var listItem = $(`<li id="${sectionName}${i}"></li>`);
var link = `<a onclick="ChangeDocumentsPage('${sectionName}', ${i})">${i}</a>`;
listItem.append(link);
paginationList.append(listItem); // Append the listItem at the end of paginationList
}

//Display the rows in the table
$(`div[id="${sectionName}"]`).find(`tbody[id="${sectionName}"]`).show();

if (data.length === 0) {
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} NoDocuments"]`).show();
}

// Remove specific elements by their IDs and href attribute value
$('a#collaborationLinkFile[href="null"], a#collaborationLinkFolder, a#downloadLinkFolder, a#deletionLinkFolder').remove();

// Hide the element with the ID loadingMessage
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} Loading"]`).hide();


// Create a breadcrumb for folders using template literals
var folderBreadcrumb = `<li><a href="#" data-folderpath="" onclick="OpenFolder(null,1,'${sectionName}')" title="${sectionRootFolder}">${sectionRootFolder}</a></li>`;

// Split the path of the current folder into an array of parts using "/" as the delimiter
var pathParts = sectionCurrentFolder.split("/");

// Find the index of the sectionRootFolder in the path array
var rootFolderIndex = pathParts.indexOf(sectionRootFolder);

// Ensure that sectionRootFolder is found in the path and it's not the last element
if (rootFolderIndex !== -1 && rootFolderIndex < pathParts.length - 1) {
// Slice the array starting from the index after sectionRootFolder, then join the remaining parts back into a string
var subFolders = pathParts.slice(rootFolderIndex + 1).join("/");

// If there are subFolders, add them to the breadcrumb
if (subFolders.length > 0) {
// Split the subFolders string into an array using "/" as the delimiter
var breadcrumbFolders = subFolders.split("/");

// Generate breadcrumb HTML by mapping each folder to a list item with a link
folderBreadcrumb += breadcrumbFolders.map(folder => `<li><a href="#" data-folderpath="/${folder}" onclick="OpenFolder('/${folder}', 1, '${sectionName}')" title="${folder}">${folder}</a></li>`).join('');
}
}

//Always load the first page by default
ChangeDocumentsPage(sectionName, 1);

// Set the innerHTML of the breadcrumb container (#documentsBreadcrumb)
$(`div[id="${sectionName}"]`).find('ol#documentsBreadcrumb')[0].innerHTML = folderBreadcrumb;

removeGuidsFromFolders()
}

removeGuidsFromFolders

removeGuidsFromFolders
function removeGuidsFromFolders()
{
const guidRegex = /_[A-Fa-f0-9]{32}/;

// Select all tr elements with data-id="Folder"
const rows = document.querySelectorAll('tr[data-id="Folder"]');
//Resolve Folder Guids in Table
rows.forEach(row => {
// Get the data-name attribute value
const dataName = row.getAttribute('data-name');

// Check if data-name contains a GUID
const match = dataName.match(guidRegex);
if (match) {
// Get the GUID from the match
const guid = match[0];

// Find the <a> elements within the row
const aElements = row.querySelectorAll('a#Folder');

// Iterate through each <a> element and update its text
aElements.forEach(a => {
// Iterate over child nodes of the <a> element
a.childNodes.forEach(child => {
if (child.nodeType === Node.TEXT_NODE) {
// Update the text content of the text node
const newText = child.textContent.replace(guid, '');
child.textContent = newText;
}
});
});
}
});

const links = document.querySelectorAll('#documentsBreadcrumb a');
//Resolve Folder Guids in Breadcrumbs
links.forEach(link => {
// Get the data-folderpath attribute value
const folderPath = link.getAttribute('data-folderpath');

// Check if data-folderpath contains a GUID
const match = folderPath.match(guidRegex);
if (match) {
// Get the GUID from the match
const guid = match[0];

// Update the text content of the <a> element
const newText = link.textContent.replace(guid, '');
link.textContent = newText;
}
});
}

ChangeDocumentsPage

ChangeDocumentsPage
function ChangeDocumentsPage(sectionName, pageNumber)
{
$(`div[id="${sectionName}"]`).find(`ul#pagination-list[data-attribute="${sectionName}"]`).find(`li`).removeClass('active');
$(`div[id="${sectionName}"]`).find(`ul#pagination-list[data-attribute="${sectionName}"]`).find(`li[id="${sectionName}${pageNumber}"]`).addClass('active');
$(`div[id="${sectionName}"]`).find(`tbody[id="${sectionName}"]`).find(`tr`).hide()
$(`div[id="${sectionName}"]`).find(`tbody[id="${sectionName}"]`).find(`tr[page-number="${pageNumber}"]`).show()

if(sectionName == "Personal Tax")
{
var showUKTax = '{{ showUKTax }}';
var showUSTax = '{{ showUSTax }}';
var showIrelandTax = '{{ showIrelandTax }}';

if(showIrelandTax != "true")
{
$('tr[data-name="Ireland Tax Returns"]').hide();
}
if(showUKTax != "true")
{
$('tr[data-name="UK Tax Returns"]').hide();

}
if(showUSTax != "true")
{
$('tr[data-name="US Tax Returns"]').hide();
}
}
}

OpenFolder

OpenFolder
// Async function to open a folder
async function OpenFolder(folderName, location, sectionName)
{
const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionDocumentLibrary = $(`span[id='${sectionName} details']`).data('documentlibrary');
const sectionRelativePath = $(`span[id='${sectionName} details']`).data('relativepath');
const sectionSite = $(`span[id='${sectionName} details']`).data('site');
var sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
const sectionDocumentEntity = $(`span[id='${sectionName} details']`).data('documententity');
const sectionFolderPath = $(`span[id='${sectionName} details']`).data('folderpath');

//Hide sections while loading folder
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} NoDocuments"]`).hide();
$(`div[id="${sectionName}"]`).find(`tbody[id="${sectionName}"]`).hide();
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} Loading"]`).show();

$(`div[id="${sectionName}"]`).find(`ul#pagination-list[data-attribute="${sectionName}"]`).remove()

// Variable to store the new breadcrumb
var newBreadcrumb = "";

// Check if folderName is null
if (folderName == null) {

$(`span[id='${sectionName} details']`).data('currentfolder', sectionFolderPath);
sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
}
// Check if location is 1 (indicating a specific location)
else if (location == 1) {
var breadcrumb = "";
// Iterate over each list item anchor element with data-folderpath attribute
$(`div[id="${sectionName}"]`).find('#documentsBreadcrumb li a[data-folderpath]').each(function () {
breadcrumb += $(this).attr('data-folderpath');
// Check if the data-folderpath attribute matches the provided folderName
if ($(this).attr('data-folderpath') == folderName) {
newBreadcrumb = breadcrumb;
}
});
var newPath = sectionFolderPath + newBreadcrumb
$(`span[id='${sectionName} details']`).data('currentfolder', newPath);

sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
}
// Check if location is 0 (indicating a general location)
else if (location == 0) {
sectionCurrentFolder += folderName;
$(`span[id='${sectionName} details']`).data('currentfolder', sectionCurrentFolder);

sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
}

// Create a body object with SharePoint site, document library, folder path, and document entity
const body = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"Folder Path": `sites/${sectionSite}${sectionCurrentFolder}`,
"Document Entity": sectionDocumentEntity
};

// Show loading message
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} Loading"]`).show();

// Call GetSharePointFiles function with the body object
const getResults = await GetSharePointFiles(body);

// Check if getResults is truthy
if (getResults) {
// Call PopulateTable function with the results and hide loading message
await PopulateTable(getResults, sectionName);
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} Loading"]`).hide();

}
}

openDeleteModal

openDeleteModal
// Function to open a delete confirmation modal
function openDeleteModal(fileName, fileID, sectionName) {
// Set the file name in the modal
document.querySelector('#DeleteModal .sp-item-name span span').innerText = fileName;

// Attach a click event handler to the "Delete" button in the modal
$('div#DeleteModal button[aria-label="Delete"]').click(() => deleteFile(fileID, sectionName));

// Open the delete confirmation modal
$("#DeleteModal").modal();
}

openModal

openModal
// Function to open a modal by ID
function openModal(modalid, sectionName) {
// Use jQuery to open the modal with the specified ID
$("#" + modalid).modal();

// Add the onclick function for the "Add Files" button
$("#" + modalid).find("#addFilesButton").on("click", function () {
UploadFile(sectionName);
});
$("#" + modalid).find("#createFolderButton").on("click", function () {
CreateFolder(sectionName);
});
}

NotifyTeam

NotifyTeam
async function NotifyTeam(sectionName, serviceLine, sectionCurrentFolder)
{
console.log("Notifying Team")
var teamToNotify = serviceLine;
var lastEmailSent = $(`span[id='LastEmailSentdetails']`).data(`${serviceLine}`);

if(serviceLine == "Personal Tax")
{
console.log(`sectionCurrentFolder: ${sectionCurrentFolder}`);
if (sectionCurrentFolder.includes("UK Tax Returns")) {
var lastEmailSent = $(`span[id='LastEmailSentdetails']`).data(`UK Tax`);
var teamToNotify = "UK Tax";
serviceLine = "UK Tax";
}
if (sectionCurrentFolder.includes("US Tax Returns")) {
var lastEmailSent = $(`span[id='LastEmailSentdetails']`).data(`US Tax`);
var teamToNotify = "US Tax";
serviceLine = "US Tax";
}
if (sectionCurrentFolder.includes("Ireland Tax Returns")) {
var lastEmailSent = $(`span[id='LastEmailSentdetails']`).data(`Ireland Tax`);
var teamToNotify = "Ireland Tax";
serviceLine = "Ireland Tax";
}
}

console.log(`teamToNotify: ${teamToNotify}`);
console.log(`lastEmailSent: ${lastEmailSent}`);

var lastEmailSentDate = lastEmailSent ? new Date(lastEmailSent) : null;
var currentDate = new Date();

// If lastEmailSent is not set, or the difference is greater than 10 minutes
if (!lastEmailSentDate || (currentDate - lastEmailSentDate) / (1000 * 60) > 10) {

$(`span[id='LastEmailSentdetails']`).data(`${serviceLine}`, currentDate);
console.log("Last email was sent over 10 minutes ago, or it has not yet been set.");

const sectionContact = $(`span[id='${sectionName} details']`).data('contact');
// Create body for upload request
const notificationbody = {
"Contact" : sectionContact,
"ServiceLine" : teamToNotify
};

var notificationResponse = NotifyTeamOfFileUpload(notificationbody);
console.log(`notificationResponse: ${notificationResponse}`);

var fieldsToUpdate = await getLastEmailedFields(teamToNotify)
console.log("fieldsToUpdate");
console.log(fieldsToUpdate);
if(fieldsToUpdate)
{
var updateresponse = await UpdateEntityFields("contacts", sectionContact, fieldsToUpdate);

if(updateresponse)
{
console.log("Record Updated")
}
}


} else {
console.log("Last email was sent within the last 10 minutes.");
}
}

UpdateEntityFields

UpdateEntityFields
async function UpdateEntityFields(entityLogicalName, recordID, payload)
{
return new Promise((resolve) => {
webapi.safeAjax({
type: "PATCH",
url: "/_api/" + entityLogicalName + "(" + recordID + ")",
contentType: "application/json",
data: JSON.stringify(payload),
success: function (res) {
setTimeout(() => {
resolve("Record Has Been Submitted");
}, 10);
}
});
});
};

getLastEmailedFields

getLastEmailedFields
async function getLastEmailedFields(teamToNotify) 
{
const notificationFields = [
{
"ServiceLines": [ "Personal Tax", "Ireland Tax" ],
"LastEmailedField": "tt_lastemailsentirelandtax"
},
{
"ServiceLines": [ "Personal Tax", "UK Tax" ],
"LastEmailedField": "tt_lastemailsentuktax"
},
{
"ServiceLines": [ "Personal Tax", "US Tax" ],
"LastEmailedField": "tt_lastemailsentustax"
},
{
"ServiceLines": [ "Audit" ],
"LastEmailedField": "tt_lastemailsentaudit"
},
{
"ServiceLines": [ "Accounts" ],
"LastEmailedField": "tt_lastemailsentaccounts"
},
{
"ServiceLines": [ "Business Advisory" ],
"LastEmailedField": "tt_lastemailsentbusinessadvisory"
},
{
"ServiceLines": [ "Corporate Finance" ],
"LastEmailedField": "tt_lastemailsentcorporatefinance"
},
{
"ServiceLines": [ "Corporation Tax" ],
"LastEmailedField": "tt_lastemailsentbusinesstax"
},
{
"ServiceLines": [ "Digital" ],
"LastEmailedField": "tt_lastemailsentdigital"
},
{
"ServiceLines": [ "Employment Tax" ],
"LastEmailedField": "tt_lastemailsentemploymenttax"
},
{
"ServiceLines": [ "Funds Tax" ],
"LastEmailedField": "tt_lastemailsentfundstax"
},
{
"ServiceLines": [ "General Documents" ],
"LastEmailedField": "tt_lastemailsentgeneral"
},
{
"ServiceLines": [ "Ireland Business Tax" ],
"LastEmailedField": "tt_lastemailsentirelandbts"
},
{
"ServiceLines": [ "Partnerships" ],
"LastEmailedField": "tt_lastemailsentpartnerships"
},
{
"ServiceLines": [ "Payroll" ],
"LastEmailedField": "tt_lastemailsentpayroll"
},
{
"ServiceLines": [ "Research And Development" ],
"LastEmailedField": "tt_lastemailsentrandd"
},
{
"ServiceLines": [ "Risk And Assurance" ],
"LastEmailedField": "tt_lastemailsentriskandassurance"
},
{
"ServiceLines": [ "Trusts" ],
"LastEmailedField": "tt_lastemailsenttrusts"
},
{
"ServiceLines": [ "Virtual Finance Office" ],
"LastEmailedField": "tt_lastemailsentvirtualfinanceoffice"
},
];

const newNotificationDate = new Date();
var formatted_date = (newNotificationDate.getMonth() + 1) + "/" + newNotificationDate.getDate() + "/" + newNotificationDate.getFullYear() + " " + newNotificationDate.getHours() + ":" + newNotificationDate.getMinutes() + ":" + newNotificationDate.getSeconds();

const filteredFields = notificationFields.filter(field => field.ServiceLines.includes(teamToNotify));
var fieldsToUpdate = filteredFields.map(field => field.LastEmailedField);

var notificationObject = {};
fieldsToUpdate.forEach(field => {
notificationObject[field] = formatted_date;
});

return notificationObject;
}

GrantCollaborationAccessToFile

GrantCollaborationAccessToFile
async function GrantCollaborationAccessToFile(sectionName, fileID)
{
const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionDocumentLibrary = $(`span[id='${sectionName} details']`).data('documentlibrary');
const sectionServiceLine = $(`span[id='${sectionName} details']`).data('serviceline');
const sectionContact = $(`span[id='${sectionName} details']`).data('contact');
// Create body for upload request
const uploadbody = {
"Contact" : sectionContact,
"SharePointSite" : sectionSharePointSite,
"DocumentLibrary" : sectionDocumentLibrary,
"ServiceLine" : sectionServiceLine,
"FileID" : fileID
};

$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} Loading"]`).show();
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} NoDocuments"]`).hide();

var collabResponse = GrantSharePointCollaborationAccess(uploadbody);
console.log(`collabResponse: ${collabResponse}`);
}

ExtractDetailsFromFile

ExtractDetailsFromFile
async function ExtractDetailsFromFile(sectionName)
{
const AIFundsTIRTesting = '{{ AIFundsTIRTesting }}';

var testingboolean = false;
if(AIFundsTIRTesting == "enabled"){
testingboolean = true;
}

var extractionBody = {
"ContactID" : "{{ contact }}",
"RecordID" : "{{ params.id }}",
"SectionName" : sectionName,
"Testing" : testingboolean
}

// Perform the file download and await the result
var extractionResponse = ExtractDataFromSharePointFile(sectionName, extractionBody);
console.log(`extractionResponse: ${extractionResponse}`);
}

ExtractDetailsFromFile

const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');

// Extract the server-relative path from the current folder
const serverRelativePath = sectionCurrentFolder.slice(1);

downloadFile

// Async function to download a file from SharePoint
async function downloadFile(fileName, fileID, sectionName)
{
const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');

// Extract the server-relative path from the current folder
const serverRelativePath = sectionCurrentFolder.slice(1);

// Prepare body for the file download request
const downloadBody = {
"SharePoint Site": sectionSharePointSite,
"Server Relative Path": serverRelativePath,
"File Name": fileName
};

// Perform the file download and await the result
const downloadResult = await DownloadFileFromSharePoint(downloadBody);

// Check if the file download was successful
if (downloadResult)
{
// Call the downloadSharePointFile function with the download result and file name
downloadSharePointFile(downloadResult, fileName);
}
}

downloadSharePointFile

// Function to download a SharePoint file
function downloadSharePointFile(data, name = "myData.txt")
{
// Convert base64 data to ArrayBuffer
const arrBuffer = base64ToArrayBuffer(data.Content);

// Create a Blob from the ArrayBuffer with the specified content type
const blob = new Blob([arrBuffer], { type: data.ContentType });

// Create an 'a' element with properties for downloading the file
const a = Object.assign(document.createElement('a'), {
href: window.URL.createObjectURL(blob),
style: "display:none",
download: name
});

// Append the 'a' element to the document body
document.body.appendChild(a);

// Simulate a click on the 'a' element to trigger the download
a.click();

// Revoke the Object URL to free up resources
window.URL.revokeObjectURL(a.href);

// Remove the 'a' element from the document body
a.remove();
}

base64ToArrayBuffer

// This function converts a base64 encoded string to an ArrayBuffer
function base64ToArrayBuffer(data) {
// Decode the base64 string using window.atob
var binaryString = window.atob(data);
// Get the length of the decoded binary string
var binaryLen = binaryString.length;
// Create a new Uint8Array to hold the bytes
var bytes = new Uint8Array(binaryLen);
// Iterate through each character in the binary string
for (var i = 0; i < binaryLen; i++) {
// Get the ASCII value of the character
var ascii = binaryString.charCodeAt(i);
// Store the ASCII value in the Uint8Array
bytes[i] = ascii;
}
// Return the Uint8Array representing the ArrayBuffer
return bytes;
};

deleteFile

// Async function to delete a file
async function deleteFile(fileID, sectionName)
{
const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionDocumentLibrary = $(`span[id='${sectionName} details']`).data('documentlibrary');
const sectionSite = $(`span[id='${sectionName} details']`).data('site');
const sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
const sectionDocumentEntity = $(`span[id='${sectionName} details']`).data('documententity');

// Select the delete button
const deleteButton = $('button#deleteFileButton');

// Set the delete button to a loading state with a spinning cog and "Processing" text
deleteButton.empty().append('<span class="fa fa-cog fa-spin" style="display: inline-block !important" aria-hidden="true"></span>');
deleteButton.append(" Processing ");

// Disable the delete button during processing
deleteButton.prop("disabled", true);

// Prepare the body for file deletion
var deletionBody = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"FileID": fileID
};

// Perform the file deletion operation and await the result
const deletionResult = await DeleteFileFromSharePoint(deletionBody);

// Check if file deletion was successful
if (deletionResult) {
// Prepare body for retrieving updated SharePoint files
var body = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"Folder Path": `sites/${sectionSite}${sectionCurrentFolder}`,
"Document Entity": sectionDocumentEntity
};

// Retrieve updated SharePoint files
const getResults = await GetSharePointFiles(body);

// Check if file retrieval was successful
if (getResults) {
// Populate the table with the updated files
PopulateTable(getResults, sectionName);

// Remove the click event handler for the delete button in the modal
$('div#DeleteModal').find('button[aria-label="Delete"]').off('click');

// Click the close button in the modal
$('div#DeleteModal').find('button[aria-label="Close"]').click();

// Enable the delete button and update its text
deleteButton.prop("disabled", false).text("Delete");
}
}
}

resyncDocuments

async function resyncDocuments(sectionName)
{

$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} Loading"]`).show();
$(`div[id="${sectionName}"]`).find(`div[id="${sectionName} NoDocuments"]`).hide();

const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionDocumentLibrary = $(`span[id='${sectionName} details']`).data('documentlibrary');
const sectionSite = $(`span[id='${sectionName} details']`).data('site');
const sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
const sectionDocumentEntity = $(`span[id='${sectionName} details']`).data('documententity');

var body = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"Folder Path": `sites/${sectionSite}${sectionCurrentFolder}`,
"Document Entity": sectionDocumentEntity
};

// Retrieve updated SharePoint files
const getResults = await GetSharePointFiles(body);

// Check if file retrieval was successful
if (getResults) {
// Populate the table with the updated files
PopulateTable(getResults, sectionName);
}
}

UploadFile

async function UploadFile(sectionName)
{
const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionDocumentLibrary = $(`span[id='${sectionName} details']`).data('documentlibrary');
const sectionSite = $(`span[id='${sectionName} details']`).data('site');
const sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
const sectionDocumentEntity = $(`span[id='${sectionName} details']`).data('documententity');

// Select the delete button
const uploadButton = $('button#addFilesButton');

// Set the delete button to a loading state with a spinning cog and "Processing" text
uploadButton.empty().append('<span class="fa fa-cog fa-spin" style="display: inline-block !important" aria-hidden="true"></span>');
uploadButton.append(" Processing ");

// Disable the delete button during processing
uploadButton.prop("disabled", true);

var filesToUpload = $('#fileInput')[0].files

// Loop through each file for upload
if(filesToUpload.length >= 1)
{
for (let i = 0; i < filesToUpload.length; i++) {
const file = filesToUpload[i];

// Create FormData and append file information
const formData = new FormData();
formData.append('file', file);

// Create body for upload request
const uploadbody = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"Folder Path": sectionCurrentFolder,
"FileName": file.name
};

// Append key-value pairs from uploadbody to FormData
for (const [key, value] of Object.entries(uploadbody)) {
formData.append(key, value);
}

// Perform the file upload and await the result
const uploadResult = await UploadFileToSharePoint(formData);

var uploadFileID = parseInt(uploadResult.FileID);
if(uploadFileID)
{
GrantCollaborationAccessToFile(sectionName, uploadFileID);
};

// Check if upload was successful and if it's the last file in the list
if (uploadResult && i === filesToUpload.length - 1) {
// Prepare body for retrieving updated SharePoint files
const body = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"Folder Path": `sites/${sectionSite}${sectionCurrentFolder}`,
"Document Entity": sectionDocumentEntity
};

var serviceLinetoAlert = $(`span[id='${sectionName} details']`).data('serviceline')
const notificationSentToTeam = await NotifyTeam(sectionName, serviceLinetoAlert, sectionCurrentFolder)

// Retrieve updated SharePoint files
const getResults = await GetSharePointFiles(body);

// Check if file retrieval was successful
if (getResults) {
// Populate the table with the updated files
PopulateTable(getResults, sectionName);
// Close the upload modal, clear file input, enable the upload button, and update its text
$('div#UploadModal').find('button[aria-label="Close"]').click();
$('input#fileInput')[0].value = "";
uploadButton.prop("disabled", false).text("Add Files");
}
}
}

var AIExtractionEnabled = '{{ AIExtractionEnabled }}';

console.log(`AIExtractionEnabled: ${AIExtractionEnabled}`);
const AIEnabledSections = ["Employments", "Prior Year Form 1065 and Schedule K-1s"]
if(AIEnabledSections.includes(sectionName) && AIExtractionEnabled == "enabled")
{
ExtractDetailsFromFile(sectionName);
}
}
else
{
uploadButton.prop("disabled", false).text("Add Files");
}
};

clearModals

// Function to clear input fields in modals
function clearModals()
{
// Clear the value of the file input field in the modal
$('input#fileInput')[0].value = "";

// Clear the value of the folder name input field in the modal
$(`div#NewFolderModal`).find('input#FolderName').val('');

// Remove the onclick function from the "Add Files" button
$("#addFilesButton").off("click");
$("#createFolderButton").off("click");
}

CreateFolder

// Async function to create a new folder in SharePoint
async function CreateFolder(sectionName)
{
const sectionSharePointSite = $(`span[id='${sectionName} details']`).data('sharepointsite');
const sectionDocumentLibrary = $(`span[id='${sectionName} details']`).data('documentlibrary');
const sectionSite = $(`span[id='${sectionName} details']`).data('site');
const sectionCurrentFolder = $(`span[id='${sectionName} details']`).data('currentfolder');
const sectionDocumentEntity = $(`span[id='${sectionName} details']`).data('documententity');
// Select the create folder button
const createFolderButton = $('button#createFolderButton');

// Set the create folder button to a loading state with a spinning cog and "Processing" text
createFolderButton.empty().append('<span class="fa fa-cog fa-spin" style="display: inline-block !important" aria-hidden="true"></span>');
createFolderButton.append(" Processing ");

// Disable the create folder button during processing
createFolderButton.prop("disabled", true);

// Get the new folder name from the input field
var newFoldername = $(`div#NewFolderModal`).find('input#FolderName')[0].value;

// Create the new folder path
var newFolderpath = `${sectionCurrentFolder.split(sectionDocumentLibrary)[1]}/${newFoldername}`;
// Prepare body for creating a new folder
const createFolderBody = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"New Folder Path": newFolderpath
};

// Perform the folder creation and await the result
const createResult = await CreateFolderInSharePoint(createFolderBody);

// Check if folder creation was successful
if (createResult) {
// Prepare body for retrieving updated SharePoint files
const body = {
"SharePoint Site": sectionSharePointSite,
"Document Library": sectionDocumentLibrary,
"Folder Path": `sites/${sectionSite}${sectionCurrentFolder}`,
"Document Entity": sectionDocumentEntity
};

// Retrieve updated SharePoint files
const getResults = await GetSharePointFiles(body);

// Check if file retrieval was successful
if (getResults) {
// Populate the table with the updated files
PopulateTable(getResults, sectionName);

// Close the new folder modal, enable the create folder button, clear input field
$('div#NewFolderModal').find('button[aria-label="Close"]').click();
createFolderButton.prop("disabled", false).text("Create Folder");
$('input#FolderName').val('');
}
}
}